package cn.seecoder.ai.serviceImpl;

import cn.seecoder.ai.dao.AnalysisConfigRepository;
import cn.seecoder.ai.dao.AnalysisVisualizationRepository;
import cn.seecoder.ai.dao.FileFieldRepository;
import cn.seecoder.ai.enums.AnalysisFunctionEnum;
import cn.seecoder.ai.exception.AIExternalException;
import cn.seecoder.ai.model.po.AnalysisConfig;
import cn.seecoder.ai.model.po.AnalysisVisualization;
import cn.seecoder.ai.model.po.FileField;
import cn.seecoder.ai.model.vo.AnalysisVisualizationVO;
import cn.seecoder.ai.service.AnalysisVisualizeService;
import cn.seecoder.ai.service.FileAnalysisService;
import cn.seecoder.ai.utils.POJOConverter;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author DingXiaoyu
 * @date 2023/4/16 15:25
 */
@Service
public class AnalysisVisualizeServiceImpl implements AnalysisVisualizeService {

    @Autowired
    AnalysisVisualizationRepository analysisVisualizationRepository;

    @Autowired
    AnalysisConfigRepository analysisConfigRepository;

    @Autowired
    FileAnalysisService fileAnalysisService;

    @Autowired
    FileFieldRepository fileFieldRepository;

    @Override
    public List<AnalysisVisualizationVO> getVisualization(Integer configId, Integer userId) {
        List<AnalysisVisualization> analysisVisualizations=analysisVisualizationRepository.findByAnalysisConfigIdAndUserId(configId,userId);
        return analysisVisualizations.stream().map(this::toVO).collect(Collectors.toList());
    }

    @Override
    public AnalysisVisualizationVO visualize(Integer configId, Integer userId, AnalysisFunctionEnum func) {
        AnalysisConfig analysisConfig=analysisConfigRepository.findById(configId).get();
        checkChooseColumns(analysisConfig.getFileInfoId(),analysisConfig.getChosenColumns(),func);
        AnalysisVisualization analysisVisualization=new AnalysisVisualization();
        analysisVisualization.setAnalysisConfigId(configId);
        analysisVisualization.setFileInfoId(analysisConfig.getFileInfoId());
        analysisVisualization.setAnalysisFunction(func);
        analysisVisualization.setUserId(userId);
        String map=doAnalysis(analysisConfig.getFileInfoId(),analysisConfig.getChosenColumns(),func);
        analysisVisualization.setAnalysisResult(map);
        analysisVisualizationRepository.save(analysisVisualization);
        return toVO(analysisVisualization);
    }

    private AnalysisVisualization toPO(AnalysisVisualizationVO analysisVisualizationVO){
        return (AnalysisVisualization) POJOConverter.convert(analysisVisualizationVO);
    }

    private AnalysisVisualizationVO toVO(AnalysisVisualization analysisVisualization){
        return (AnalysisVisualizationVO)POJOConverter.convert(analysisVisualization);
    }

    private void checkChooseColumns(Integer fileInfoId, List<String> chosenColumns, AnalysisFunctionEnum func) {
        FileField fileField;
        switch (func){
            case DATA_DISTRIBUTION:
                if (chosenColumns.size()!=1){
                    throw AIExternalException.columnsNumberWrong();
                }
                break;
            case SCATTER_PLOT:
            case PEARSON:
                if (chosenColumns.size()!=2){
                    throw AIExternalException.columnsNumberWrong();
                }
                fileField=fileFieldRepository.findByFileInfoIdAndFieldName(fileInfoId,chosenColumns.get(0)).get(0);
                if (fileField.getDataType().equals("string")){
                    throw AIExternalException.columnsTypeWrong();
                }
                fileField=fileFieldRepository.findByFileInfoIdAndFieldName(fileInfoId,chosenColumns.get(1)).get(0);
                if (fileField.getDataType().equals("string")){
                    throw AIExternalException.columnsTypeWrong();
                }
                break;
            case STATISTICS:
            case SKEWNESS_KURTOSIS:
                if (chosenColumns.size()!=1){
                    throw AIExternalException.columnsNumberWrong();
                }
                fileField=fileFieldRepository.findByFileInfoIdAndFieldName(fileInfoId,chosenColumns.get(0)).get(0);
                if (fileField.getDataType().equals("string")){
                    throw AIExternalException.columnsTypeWrong();
                }
                break;
        }
    }

    private String doAnalysis(Integer fileInfoId, List<String> chosenColumns, AnalysisFunctionEnum func) {
        switch (func){
            case DATA_DISTRIBUTION:
                FileField fileField=fileFieldRepository.findByFileInfoIdAndFieldName(fileInfoId,chosenColumns.get(0)).get(0);
                Map<String,Integer> map=fileAnalysisService.dataDistribution(fileInfoId,chosenColumns.get(0),fileField.getDataType());
                return JSON.toJSONString(map);
            case SCATTER_PLOT:
                List<Map<String,Double>> list=fileAnalysisService.scatterPlot(fileInfoId,chosenColumns.get(0),chosenColumns.get(1));
                return JSON.toJSONString(list);
            case STATISTICS:
                Map<String,Double> ans1=fileAnalysisService.statistics(fileInfoId,chosenColumns.get(0));
                return JSON.toJSONString(ans1);
            case SKEWNESS_KURTOSIS:
                Map<String,Double> ans2=fileAnalysisService.skewnessKurtosis(fileInfoId,chosenColumns.get(0));
                return JSON.toJSONString(ans2);
            case PEARSON:
                Map<String,Double> ans3=fileAnalysisService.pearson(fileInfoId,chosenColumns.get(0),chosenColumns.get(1));
                return JSON.toJSONString(ans3);
        }
        return null;
    }
}
